package com.loong.game2048.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.loong.game2048.annotation.Authorize;
import com.loong.game2048.module.*;
import com.loong.game2048.module.vo.GameDataVo;
import com.loong.game2048.module.vo.Result;
import com.loong.game2048.server.GameService;
import com.loong.game2048.server.ScopeService;
import com.loong.game2048.util.RedisUtils;
import com.loong.game2048.util.ResultUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;

//以json格式返回数据
@RestController
public class GameController {

    @Resource
    private RedisUtils redisUtils;

    @Autowired
    private ObjectMapper mapper ;

    @Resource
    private ScopeService scopeService;

    @Resource
    private GameService gameService;

    /**
     * 开始游戏
     * @param request
     * @return
     */
    @Authorize
    @GetMapping("/start")
    public Result start(HttpServletRequest request){
        Result result = new Result();
        GameDataVo vo = new GameDataVo();

        Game2048 game = new Game2048();
        //初始化数据
        game.startGame();

        String openId = ResultUtils.getOpenId(request);
        //删除原来的记录
        redisUtils.lTrim("game:"+openId,1,0);
        //创建游戏数据记录
        redisUtils.lSet("game:"+openId,game,64800L);

        vo.setGameState(ResultCode.GAME_BEGIN);
        vo.setHigest(game.getHighest());
        vo.setHasMoved(true);
        vo.setScore(game.getScore());
        vo.setTiles(game.getTiles());

        if (scopeService.scopeHasExit(openId)>0){
            vo.setHigest(scopeService.getScope(openId,1));
        }else {
            //数据库中没有游戏数据，插入分数数据
            scopeService.addScope(openId,1,0);
        }

        result.setCode(ResultCode.SUCCESS);
        result.setMsg("创建游戏成功");
        result.setData(vo);
        return result;
    }


    /**
     * 游戏进行
     * @param move 1，2，3，4分别代表上下左右移动
     * @param request
     * @return
     */
    @Authorize
    @GetMapping("/run")
    public Result run(@RequestParam(name = "move") String move,HttpServletRequest request){
        Result result = new Result();
        GameDataVo vo = new GameDataVo();

        String openId = ResultUtils.getOpenId(request);
        String key = "game:"+openId;
        //获得列表最后一个的对象
        Game2048 game =  mapper.convertValue(redisUtils.lGetIndex(key,-1), new TypeReference<Game2048>() { });
        //操作
        switch (move){
            //up
            case "1":
                vo.setHasMoved(game.moveUp());
                vo.setScore(game.getScore());
                vo.setGameState(game.getGameState());
                break;
            //down
            case "2":
                vo.setHasMoved(game.moveDown());
                vo.setScore(game.getScore());
                vo.setGameState(game.getGameState());
                break;
            //left
            case "3":
                vo.setHasMoved(game.moveLeft());
                vo.setScore(game.getScore());
                vo.setGameState(game.getGameState());
                break;
            //right
            case "4":
                vo.setHasMoved(game.moveRight());
                vo.setScore(game.getScore());
                vo.setGameState(game.getGameState());
                break;
            default:
                result.setCode(ResultCode.PARAMETER_ERROR);
                result.setMsg("错误参数");
                break;
        }
        vo.setTiles(game.getTiles());
        if (scopeService.getScope(openId,1)>=game.getScore()){
            vo.setHigest(scopeService.getScope(openId,1));
        }else{
            //分数比数据库中的高，修改数据
            vo.setHigest(game.getScore());
            scopeService.updateScope(openId,1,game.getScore());
        }
        result = ResultUtils.setResult(vo);
        //当redis缓存列表中
        if (redisUtils.lGetListSize(key)>3){
            redisUtils.lRemove(key,1L,redisUtils.lGetIndex(key,0L));
        }
        redisUtils.lSet(key,game,64800L);
        return result;
    }

    /**
     * 撤销操作
     * @param request
     * @return
     */
    @Authorize
    @GetMapping("/revocation")
    public Result revocation(HttpServletRequest request){
        Result result = new Result();
        GameDataVo vo = new GameDataVo();

        String openId = ResultUtils.getOpenId(request);
        String key = "game:"+openId;

        //redis保留一条数据
        if (redisUtils.lGetListSize(key)>1){
            //移除表尾的元素
            redisUtils.lRemove(key,1L,redisUtils.lGetIndex(key,-1L));
            result.setMsg("撤销成功");
            //获得列表最后一个的对象
            Game2048 game = (Game2048) redisUtils.lGetIndex(key,-1);
            vo.setTiles(game.getTiles());
            vo.setHasMoved(true);
            vo.setScore(game.getScore());
            vo.setGameState(game.getGameState());
            vo.setHigest(scopeService.getScope(openId,1));
            result.setData(vo);
        }else {
            result.setMsg("你已经没有可以撤销操作了");
            Game2048 game = (Game2048) redisUtils.lGetIndex(key,0);
            vo.setTiles(game.getTiles());
            vo.setHasMoved(true);
            vo.setScore(game.getScore());
            vo.setGameState(4);
            vo.setHigest(scopeService.getScope(openId,1));
            result.setData(vo);
        }
        return result;
    }


    /**
     * 获得所有游戏
     * @return
     */
    @GetMapping("/getAllGames")
    public Result getAllGames(){
        return new Result(gameService.getAllGame());
    }

    /**
     * 获得用户的最高分
     * @return
     */
    @Authorize
    @GetMapping("/getHightScope")
    public Result getHightScope(HttpServletRequest request){
        String openId = ResultUtils.getOpenId(request);
        return new Result(scopeService.getScopeVo(openId,1));
    }

    /**
     * 获得游戏排行榜
     * @return
     */
    @Authorize
    @GetMapping("/getScopeRank")
    public Result getScopeRank(){
        return new Result(scopeService.getAllScope());
    }

    /**
     * 新增游戏标签，用于论坛发帖新增使用
     * @param tag
     * @return
     */
    @GetMapping("/addTag")
    public Result addTag(@RequestParam("tag") String tag){
        Game game = new Game();
        game.setGame(tag);
        return new Result(gameService.addTag(game));
    }

}
